#include "Rp2Node.h"


using namespace Rp2;

//---------------------------------------------------------------------------------------------------
Node::Node()
{
}
//---------------------------------------------------------------------------------------------------
Node::~Node()
{
}
//---------------------------------------------------------------------------------------------------
int Node::AttachChild(Spatial* pkChild)
{

	assert(pkChild && !pkChild->GetParent());

	pkChild->SetParent(this);

	// attach child in first available slot (if any)
	int iQuantity = (int)m_kChild.size();


	for (int i = 0; i < iQuantity; i++)
	{
		if (m_kChild[i] == 0)
		{
			m_kChild[i] = pkChild;
			return i;
		}
	}

	// all slot used, increase array size
	m_kChild.push_back(pkChild);
	return iQuantity;

	return 0;

}
//---------------------------------------------------------------------------------------------------
int Node::DetachChild(Spatial* pkChild)
{
	if (pkChild)
	{
		// search to see if child exists
		for (int i = 0; i < (int)m_kChild.size(); i++)
		{
			if (m_kChild[i] == pkChild)
			{
				pkChild->SetParent(0);
				m_kChild[i] = 0;
				return i;
			}
		}
	}

	return -1;
}
//---------------------------------------------------------------------------------------------------
void Node::UpdateWorldData(double dAppTime)
{
	Spatial::UpdateWorldData(dAppTime);

	for (int i = 0; i < (int)m_kChild.size(); i++)
	{
		Spatial* pkChild = m_kChild[i];
		if (pkChild)
		{
			pkChild->UpdateGS(dAppTime, false);
		}
	}
}
//---------------------------------------------------------------------------------------------------
void Node::UpdateWorldBound()
{
    if (!WorldBoundIsCurrent)
    {
        bool bFoundFirstBound = false;
        for (int i = 0; i < (int)m_kChild.size(); i++)
        {
            Spatial* pkChild = m_kChild[i];
            if (pkChild)
            {
                if (bFoundFirstBound)
                {
                    // merge current world bound with child world bound
                    WorldBound->GrowToContain(pkChild->WorldBound);
                }
                else
                {
                    // set world bound to first non-null child world bound
                    bFoundFirstBound = true;
                    WorldBound->CopyFrom(pkChild->WorldBound);
                }
            }
        }
    }
}
//---------------------------------------------------------------------------------------------------
void Node::UpdateState(std::vector<GlobalState*>* akGStack, std::vector<Light*>* pkLStack)
{
	for (int i = 0; i < (int)m_kChild.size(); i++)
	{
		Spatial* pkChild = m_kChild[i];
		if (pkChild)
		{
			pkChild->UpdateRS(akGStack, pkLStack);
		}
	}

}
//---------------------------------------------------------------------------------------------------
void Node::GetVisibleSet (Culler& rkCuller, bool bNoCull)
{
    int i;
    for (i = 0; i < (int)m_kEffects.size(); i++)
    {
        // This is a global effect.  Place a 'begin' marker in the visible
        // set to indicate the effect is active.
        rkCuller.Insert(this,m_kEffects[i]);
    }

    // All Geometry objects in the subtree are added to the visible set.  If
    // a global effect is active, the Geometry objects in the subtree will be
    // drawn using it.
    for (i = 0; i < (int)m_kChild.size(); i++)
    {
        Spatial* pkChild = m_kChild[i];
        if (pkChild)
        {
            pkChild->OnGetVisibleSet(rkCuller,bNoCull);
        }
    }

    for (i = 0; i < (int)m_kEffects.size(); i++)
    {
        // Place an 'end' marker in the visible set to indicate that the
        // global effect is inactive.
        rkCuller.Insert(0,0);
    }
}
//---------------------------------------------------------------------------------------------------